#!/bin/bash
#######################################################
# Author: liangliangSu
# Created Time: 2024-09-01 12:42
# Email: sll917@outlook.com
# Version: V1.0
# File Name: 07printf格式化输出.sh
#######################################################
echo '(1)------------------完美分割线---------------------'
: '
printf 命令用于格式化输出， 是echo命令的增强版。
它是 C 语言 printf()库函数的一个有限的变形，并且在语法上有些不同。
注意：printf 由 POSIX 标准所定义，移植性要比 echo 好。
'
#如同 echo 命令，printf 命令也可以输出简单的字符串：
printf "Hello, Shell\n"
#Hello, Shell
#printf 不像 echo 那样会自动换行，必须显式添加换行符(\n)。
: '
printf 命令的语法：
printf format-string [arguments...]
format-string 为格式控制字符串，arguments 为参数列表。
printf()在 C 语言入门教程中已经讲到，功能和用法与 printf 命令类似，
请查看：C 语言格式输出函数 printf()详解
这里仅说明与 C 语言 printf()函数的不同：
- printf 命令不用加括号 
- format-string 可以没有引号，但最好加上，单引号双引号均可。 
- 参数多于格式控制符(%)时，format-string 可以重用，可以将所有参数都转换。 
- arguments 使用空格分隔，不用逗号。
'
#请看下面的例子：
# format-string 为双引号
printf "%d %s\n" 1 "abc"
#1 abc
# 单引号与双引号效果一样
printf '%d %s\n' 1 "abc"
#1 abc
# 没有引号也可以输出
printf %s abcdef
#abcdef
# 格式只指定了一个参数，但多出的参数仍然会按照该格式输出，format-string 被重用
printf %s abc def
#abcdef
printf "%s\n" abc def
#abc
#def
printf "%s %s %s\n" a b c d e f g h i j
#a b c
#d e f
#g h i
#j
# 如果没有 arguments，那么 %s 用 NULL 代替，%d 用0代替
printf "%s and %d \n"
#and 0
# 如果以 %d 的格式来显示字符串，那么会有警告，提示无效的数字，此时默认置为0
printf "The first program always prints'%s,%d\n'" 
: '
注意:
根据 POSIX 标准，浮点格式%e、%E、%f、%g与%G是“不需要被支持”。
这是因为 awk 支持浮点预算，且有它自己的 printf 语句。
这样 Shell 程序中需要将浮点数值进行格式化的打印时，可使用小型的 awk 程序实现。
然而，内建于 bash、ksh93 和 zsh 中的 printf 命令都支持浮点格式。
'
#格式化打印： printf
#在很多时候，我们可能需要将自己的数据给他格式化输出的！ 举例来说，考试卷分数的输出，姓名
#与科目及分数之间，总是可以稍微作个比较漂亮的版面配置吧？ 例如我想要输出底下的样式：
#Name Chinese English Math Average
#DmTsai 80 60 92 77.33
#VBird 75 55 80 70.00
#Ken 60 90 70 73.33
#上表的数据主要分成五个字段，各个字段之间可使用tab 或空格键进行分隔。请将上表的资料转存
#成为printf.txt 档名，等一下我们会利用这个文件来进行几个小练习的。因为每个字段的原始数据长
#度其实并非是如此固定的(Chinese 长度就是比Name 要多)， 而我就是想要如此表示出这些数据，
#此时，就得需要打印格式管理员printf 的帮忙了！ printf 可以帮我们将资料输出的结果格式化，而
#且而支持一些特殊的字符～底下我们就来看看！
:<<!
printf '打印格式' 实际内容
选项与参数：
关于格式方面的几个特殊样式：
\a 警告声音输出
\b 退格键(backspace)
\f 清除屏幕 (form feed)
\n 输出新的一行
\r 亦即 Enter 按键
\t 水平的 [tab] 按键
\v 垂直的 [tab] 按键
\xNN NN 为两位数的数字，可以转换数字成为字符。
关于 C 程序语言内，常见的变数格式
%ns 那个 n 是数字， s 代表 string ，亦即多少个字符；
%ni 那个 n 是数字， i 代表 integer ，亦即多少整数字数；
%N.nf 那个 n 与 N 都是数字， f 代表 floating (浮点)，如果有小数字数，
!
#假设我共要十个位数，但小数点有两位，即为 %10.2f 啰！
#接下来我们来进行几个常见的练习。假设所有的数据都是一般文字(这也是最常见的状态)，因此最
#常用来分隔数据的符号就是[Tab] 啦！因为[Tab] 按键可以将数据作个整齐的排列！那么如何利用
#printf 呢？参考底下这个范例：
echo '(2)------------------完美分割线---------------------'
#范例一：将刚刚上头数据的文件 (printf.txt) 内容仅列出姓名与成绩：(用 [tab] 分隔)
printf '%s\t %s\t %s\t %s\t %s\t \n' $(cat printf.txt)
#Name Chinese English Math Average
#DmTsai 80 60 92 77.33
#VBird 75 55 80 70.00
#Ken 60 90 70 73.33
#由于printf 并不是管线命令，因此我们得要透过类似上面的功能，将文件内容先提出来给printf 作
#为后续的资料才行。如上所示，我们将每个数据都以[tab] 作为分隔，但是由于Chinese 长度太长，
#导致English 中间多了一个[tab] 来将资料排列整齐！啊～结果就看到资料对齐结果的差异了！
#另外，在printf 后续的那一段格式中，%s 代表一个不固定长度的字符串，而字符串与字符串中间就
#以\t 这个[tab] 分隔符来处理！你要记得的是，由于\t 与%s 中间还有空格，因此每个字符串间
#会有一个[tab] 与一个空格键的分隔喔！
#既然每个字段的长度不固定会造成上述的困扰，那我将每个字段固定就好啦！没错没错！这样想非常
#好！ 所以我们就将数据给他进行固定字段长度的设计吧！
#范例二：将上述资料关于第二行以后，分别以字符串、整数、小数点来显示：
echo '(3)-----------------------完美分割线--------------------------------'
printf '%10s %5i %5i %5i %8.2f \n' $(cat printf.txt | grep -v Name)
#DmTsai 80 60 92 77.33
#VBird 75 55 80 70.00
#Ken 60 90 70 73.33
#上面这一串格式想必您看得很辛苦！没关系！一个一个来解释！上面的格式共分为五个字段， %10s
#代表的是一个长度为10 个字符的字符串字段，%5i 代表的是长度为5 个字符的数字字段，至于那
#个%8.2f 则代表长度为8 个字符的具有小数点的字段，其中小数点有两个字符宽度。
#我们可以使用底下的说明来介绍%8.2f 的意义：
#字符宽度： 12345678
#%8.2f 意义：00000.00
#如上所述，全部的宽度仅有8 个字符，整数部分占有5 个字符，小数点本身(.) 占一位，小数点下
#的位数则有两位。这种格式经常使用于数值程序的设计中！这样了解乎？自己试看看如果要将小数
#点位数变成1 位又该如何处理？
#printf 除了可以格式化处理之外，他还可以依据ASCII 的数字与图形对应来显示数据喔(注3)！ 举
#例来说16 进位的45 可以得到什么ASCII 的显示图(其实是字符啦)？

echo '(4)-----------------------完美分割线--------------------------------'
#范例范例三：列出 16 进位数值 45 代表的字符为何？
printf '\x45\n'
# 这东西也很好玩～他可以将数值转换成为字符，如果你会写 script 的话，
# 可以自行测试一下，由 20~80 之间的数值代表的字符是啥喔！ ^_^
# printf 的使用相当的广泛喔！包括等一下后面会提到的awk 以及在C 程序语言当中使用的屏幕输出，

printf "%-5s %-10s %-4s\n" No Name Mark
printf "%-5s %-10s %-4.2f\n" 1 Sarath 80.3456
printf "%-5s %-10s %-4.2f\n" 2 James 90.9989
printf "%-5s %-10s %-4.2f\n" 3 Jeff 77.564
# 我们会得到如下格式化的输出：
# No Name Mark
# 1 Sarath 80.35
# 2 James 91.00
# 3 Jeff 77.56
